from flask import render_template, g, abort, request, jsonify, current_app, redirect, url_for

from info import db
from info.modules.user import user_blu
from info.utils.common import user_login_data, upload_file
from info.utils.constants import QINIU_DOMIN_PREFIX, USER_COLLECTION_MAX_NEWS
from info.utils.models import UserCollection, Category, News
from info.utils.response_code import RET, error_map


@user_blu.route('/user_info')  # 个人中心
@user_login_data
def user_info():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问, 跳转到前台首页
        return redirect(url_for("home.index"))
    return render_template("news/user.html", user=user.to_dict())


# 基本资料  一个路由完成两项工作: GET 展示资料 POST 提交资料
@user_blu.route('/base_info', methods=['GET', 'POST'])
@user_login_data
def base_info():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问
        return abort(403)

    if request.method == 'GET':
        return render_template("news/user_base_info.html", user=user.to_dict())

    # POST 提交资料
    signature = request.json.get("signature")
    nick_name = request.json.get("nick_name")
    gender = request.json.get("gender")
    # 校验参数
    if not all([signature, nick_name, gender]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    if gender not in ['MAN', 'WOMAN']:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 数据库行为: 修改用户数据
    user.signature = signature
    user.nick_name = nick_name
    user.gender = gender
    
    # 返回json结果
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 头像设置
@user_blu.route('/pic_info', methods=['GET', 'POST'])
@user_login_data
def pic_info():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问
        return abort(403)

    if request.method == 'GET':  # GET 展示页面
        return render_template("news/user_pic_info.html", user=user.to_dict())

    # POST 提交头像
    avatar_file = request.files.get("avatar")
    if not avatar_file:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    # 一般开发中, 会将静态文件分离到文件服务器, 以便提高性能
    # 读取文件的二进制格式数据
    try:
        img_bytes = avatar_file.read()
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    
    # 使用七牛云工具进行文件上传
    try:
        file_name = upload_file(img_bytes)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg=error_map[RET.THIRDERR])

    # 修改用户的头像链接
    user.avatar_url = QINIU_DOMIN_PREFIX + file_name

    # 返回json  为了让前端可以立即修改用户的头像, 需要返回头像链接
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK], data=user.to_dict())


# 修改密码
@user_blu.route('/pass_info', methods=['POST', 'GET'])
@user_login_data
def pass_info():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问
        return abort(403)

    if request.method == 'POST':
        # 获取参数
        old_password = request.json.get("old_password")
        new_password = request.json.get("new_password")
        # 校验参数
        if not all([old_password, new_password]):
            return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

        # 校验当前密码
        if not user.check_password(old_password):
            return jsonify(errno=RET.PWDERR, errmsg=error_map[RET.PWDERR])
        # 数据库行为: 修改密码
        user.password = new_password
        # 返回json
        return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])

    # GET 展示页面
    return render_template("news/user_pass_info.html")


# 我的收藏(分页显示用户收藏的新闻)
@user_blu.route('/collection')
@user_login_data
def collection():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问
        return abort(403)

    # 获取参数
    p = request.args.get("p", 1)
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    # 数据库行为: 查询用户收藏的所有新闻  分页  收藏时间倒序
    try:
        pn = user.collection_news.order_by(UserCollection.create_time.desc()).paginate(p, USER_COLLECTION_MAX_NEWS)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)

    # TODO 在我的收藏中显示收藏时间
    # for news in pn.items:
    #     news_dict = news.to_basic_dict()
    #     user_collection = UserCollection.query.filter(UserCollection.user_id==user.id, UserCollection.news_id==news.id).first()
    #     news_dict["create_time"] = user_collection.create_time

    data = {
        "news_list": [news.to_basic_dict() for news in pn.items],
        "cur_page": pn.page,
        "total_page": pn.pages
    }

    # 返回json结果
    return render_template("news/user_collection.html", data=data)

# 新闻发布
@user_blu.route('/news_release', methods=['GET', 'POST'])
@user_login_data
def news_release():
    user = g.user
    if not user:
        return abort(403)

    if request.method == 'GET': # 展示发布页面
        # 查询所有的分类
        try:
            categories = Category.query.filter(Category.id != 1).all()
        except BaseException as e:
            current_app.logger.error(e)
            return abort(500)

        # 模板渲染
        return render_template("news/user_news_release.html", categories=categories)

    # POST 提交新闻数据
    # 获取参数
    title = request.form.get("title")
    category_id = request.form.get("category_id")
    digest = request.form.get("digest")
    content = request.form.get("content")
    index_image = request.files.get("index_image")

    # 校验参数
    if not all([title, category_id, digest, content, index_image]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
        
    try:
        category_id = int(category_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    
    # 数据库行为: 增加一条新闻数据
    news = News()
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.content = content
    try:
        index_image_bytes = index_image.read()
        file_name = upload_file(index_image_bytes)
        news.index_image_url = QINIU_DOMIN_PREFIX + file_name
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg=error_map[RET.THIRDERR])
    news.user_id = user.id
    news.source = "个人发布"
    news.status = 1  # 新闻状态 1表示正在审核

    db.session.add(news)

    # 返回json
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 我的发布(分页显示用户发布的新闻)
@user_blu.route('/news_list')
@user_login_data
def news_list():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问
        return abort(403)

    # 获取参数
    p = request.args.get("p", 1)
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    # 数据库行为: 查询用户发布的所有新闻  分页  发布时间倒序
    try:
        pn = user.news_list.order_by(News.create_time.desc()).paginate(p, USER_COLLECTION_MAX_NEWS)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)

    data = {
        "news_list": [news.to_review_dict() for news in pn.items],
        "cur_page": pn.page,
        "total_page": pn.pages
    }

    # 返回json结果
    return render_template("news/user_news_list.html", data=data)


# 我的关注(分页显示用户关注的作者)
@user_blu.route('/user_follow')
@user_login_data
def user_follow():
    user = g.user
    if not user:  # 用户未登录, 拒绝访问
        return abort(403)

    # 获取参数
    p = request.args.get("p", 1)
    # 校验参数
    try:
        p = int(p)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(403)

    # 数据库行为: 查询用户关注的所有作者  分页
    try:
        pn = user.followed.paginate(p, USER_COLLECTION_MAX_NEWS)
    except BaseException as e:
        current_app.logger.error(e)
        return abort(500)

    data = {
        "author_list": [author.to_dict() for author in pn.items],
        "cur_page": pn.page,
        "total_page": pn.pages
    }

    # 返回json结果
    return render_template("news/user_follow.html", data=data)